package com.zeei.ems.base.util;

import com.zeei.ems.base.constant.GlobalConstant;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.net.URL;
import java.net.URLConnection;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import org.apache.commons.io.FilenameUtils;
public class FileUtil {
    private static Logger logger = LoggerFactory.getLogger(FileUtil.class);

    private FileUtil(){

    }

    /**
     * <pre>
     * 字符流：	以行为单位读取文件，常用于读面向行的格式化文件
     * </pre>
     *
     */
    public static void readFileByLines(String sourceFile, String targetFile) {
        File file = new File(sourceFile);
        BufferedReader reader = null;
        BufferedWriter writer = null;
        try {
            reader = new BufferedReader(new FileReader(file));
            writer = new BufferedWriter(new FileWriter(targetFile));
            String tempString = null;
            // 一次读入一行，直到读入null为文件结束
            while ((tempString = reader.readLine()) != null) {
                // 显示行号
                writer.write(tempString);
            }
            reader.close();
        } catch (IOException e) {
            logger.error(sourceFile + " save to " + targetFile + " error!", e);
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                    writer.flush();
                    writer.close();
                } catch (IOException e) {
                    logger.error("closed stream error!", e);
                }
            }
        }
    }

    public static void writeText(String filePath, String content) {
        try {
            File file = new File(filePath);
            if (!file.exists()) {
                file.createNewFile();
            }

            FileWriter fw = new FileWriter(file, true);
            BufferedWriter bw = new BufferedWriter(fw);
            bw.write(content);
            bw.close();
            fw.close();
        } catch (Exception e) {

        }
    }

    /**
     * <pre>
     * 字节流：将一个文件复制到另一个文件中
     * </pre>
     *
     */
    public static void copyFile(File sourceFile, File targetFile) throws IOException {
        BufferedInputStream inBuff = null;
        BufferedOutputStream outBuff = null;
        try {
            // 新建文件输入流并对它进行缓冲
            inBuff = new BufferedInputStream(new FileInputStream(sourceFile));

            // 新建文件输出流并对它进行缓冲
            outBuff = new BufferedOutputStream(new FileOutputStream(targetFile));

            // 缓冲数组
            byte[] b = new byte[1024 * 5];
            int len;
            while ((len = inBuff.read(b)) != -1) {
                outBuff.write(b, 0, len);
            }
            // 刷新此缓冲的输出流
            outBuff.flush();
        } finally {
            // 关闭流
            if (inBuff != null)
                inBuff.close();
            if (outBuff != null)
                outBuff.close();
        }
    }

    public static void copyFile(String orgFilePath, String targetPath, Boolean deleteOrgFile) {
        try {
            // 拷贝到数据目录，该目录永久保存
            Path dataTargetPath = Paths.get(targetPath);
            Path orgPath = Paths.get(orgFilePath);
            Files.copy(orgPath, dataTargetPath, StandardCopyOption.REPLACE_EXISTING);

            if (deleteOrgFile) {
                // 删除临时文件
                Files.deleteIfExists(orgPath);
            }
        } catch (Exception e) {

        }
    }

    public static void createDirectories(String dicrectPath) {
        try {
            if (!Files.exists(Paths.get(dicrectPath))) {
                Files.createDirectories(Paths.get(dicrectPath));
            }
        } catch (Exception e) {

        }
    }

    /***
     * <pre>
     * 	获取文件的编码格式
     *  如  UTF-8,Unicode,UTF-16BE,GBK
     * </pre>
     *
     * 默认文件是utf-8格式
     */
    public static String getCharset(String filePath) throws IOException {

        BufferedInputStream bin = new BufferedInputStream(new FileInputStream(filePath));

        int p = (bin.read() << 8) + bin.read();
        String code = null;
        switch (p) {
            case 0xefbb:
                code = GlobalConstant.UTF8;
                break;
            case 0xfffe:
                code = GlobalConstant.UNICODE;
                break;
            case 0xfeff:
                code = GlobalConstant.UTF16;
                break;
            case 0x2d2d:
                code = GlobalConstant.GBK;
                break;
            default:
                code = GlobalConstant.ANSI;
        }
        if (bin != null) {
            bin.close();
        }
        return code;
    }

    /****
     * <pre>
     * 	将非UTF-8格式的text文本转换成UTF-8的文本
     * </pre>
     *
     * @param filePath
     * @return
     * @throws IOException
     */
    public static String transformTextCodeToUTF8(String filePath) throws IOException {
        String ext = FilenameUtils.getExtension(filePath);
        if (!ext.equalsIgnoreCase("txt")) {
            return filePath;
        }
        String code = getCharset(filePath);
        if (code.equalsIgnoreCase(GlobalConstant.UTF8)) {
            return filePath;
        } else if (code.equalsIgnoreCase(GlobalConstant.ANSI)) {
            code = GlobalConstant.GBK;
        }
        // 构建一个新文件地址
        StringBuffer content = new StringBuffer();
        String newFilePath = FilenameUtils.getFullPath(filePath);
        newFilePath = newFilePath + System.currentTimeMillis() + "." + ext;
        BufferedReader bin = new BufferedReader(new InputStreamReader(new FileInputStream(filePath), code));
        String line = null;
        while ((line = bin.readLine()) != null) {
            content.append(line);
            content.append(System.getProperty("line.separator"));
        }
        bin.close();
        File newFile = new File(newFilePath);
        newFile.createNewFile();
        FileOutputStream fos = new FileOutputStream(newFile);
        Writer out = new OutputStreamWriter(fos, GlobalConstant.UTF8);
        out.write(content.toString());
        out.close();
        fos.close();

        return newFilePath;
    }

    /**
     * <pre>
     * 	删除目录（文件夹）以及目录下的文件
     * </pre>
     *
     * @param sPath
     *            被删除目录的文件路径
     * @return 目录删除成功返回true，否则返回false
     */
    public static boolean deleteDirectory(String sPath) {
        // 如果sPath不以文件分隔符结尾，自动添加文件分隔符
        if (!sPath.endsWith(File.separator)) {
            sPath = sPath + File.separator;
        }
        File dirFile = new File(sPath);
        // 如果dir对应的文件不存在，或者不是一个目录，则退出
        if (!dirFile.exists() || !dirFile.isDirectory()) {
            return false;
        }
        boolean flag = true;
        // 删除文件夹下的所有文件(包括子目录)
        File[] files = dirFile.listFiles();
        if (files != null) {
            for (int i = 0; i < files.length; i++) {
                // 删除子文件
                if (files[i].isFile()) {
                    flag = deleteFile(files[i].getAbsolutePath());
                    if (!flag)
                        break;
                } // 删除子目录
                else {
                    flag = deleteDirectory(files[i].getAbsolutePath());
                    if (!flag)
                        break;
                }
            }
        }

        if (!flag)
            return false;
        // 删除当前目录
        if (dirFile.delete()) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * <pre>
     * 删除单个文件
     * </pre>
     *
     * @param sPath
     *            被删除文件的文件名
     * @return 单个文件删除成功返回true，否则返回false
     */
    public static boolean deleteFile(String sPath) {
        boolean flag = false;
        File file = new File(sPath);
        // 路径为文件且不为空则进行删除
        if (file.isFile() && file.exists()) {
            file.delete();
            flag = true;
        }
        return flag;
    }

    /**
     *
     * <pre>
     * 	 根据路径删除指定的目录或文件，无论存在与否
     * </pre>
     *
     * @param sPath
     *            要删除的目录或文件
     * @return 删除成功返回 true，否则返回 false。
     *
     */
    public static boolean deleteFolder(String sPath) {
        boolean flag = false;
        File file = new File(sPath);
        // 判断目录或文件是否存在
        if (!file.exists()) { // 不存在返回 false
            return flag;
        } else {
            // 判断是否为文件
            if (file.isFile()) { // 为文件时调用删除文件方法
                return deleteFile(sPath);
            } else { // 为目录时调用删除目录方法
                return deleteDirectory(sPath);
            }
        }
    }

    /**
     * <pre>
     * 从文件路径中获取文件名带扩展名
     * </pre>
     *
     * @param filePath
     *            文件路径
     * @return
     */
    public static String getFileNameIncludeSuffix(String filePath) {
        int beginIndex = 0;
        if (filePath.lastIndexOf('\\') != -1) {
            filePath = filePath.replaceAll("\\\\", "/");
        }
        beginIndex = filePath.lastIndexOf('/') + 1;
        return filePath.substring(beginIndex);
    }

    /**
     * <pre>
     * 从文件路径中获取文件名不带扩展名
     * </pre>
     *
     * @param filePath
     *            文件地址
     * @return
     */
    public static String getFileNameExcludeSuffix(String filePath) {
        String fileName = getFileNameIncludeSuffix(filePath);
        return fileName.substring(0, fileName.lastIndexOf('.'));
    }

    /**
     * <pre>
     * 通过url地址下载文件到本地
     * </pre>
     *
     * @param httpUrl
     *            下载文件的地址
     * @param saveFile
     *            保存文件的地址
     * @return true 下载成功 false下载失败
     */
    public static boolean downloadByUrl(String httpUrl, String saveFile) {
        // 下载网络文件
        int byteread = 0;
        InputStream inStream = null;
        FileOutputStream fs = null;
        URL url = null;
        try {
            url = new URL(httpUrl);
            URLConnection conn = url.openConnection();
            inStream = conn.getInputStream();
            fs = new FileOutputStream(saveFile);
            byte[] buffer = new byte[1204];
            while ((byteread = inStream.read(buffer)) != -1) {
                fs.write(buffer, 0, byteread);
            }
            return true;
        } catch (Exception e) {
            logger.error(httpUrl + "download to " + saveFile + " error!", e);
            return false;
        } finally {
            if (fs != null) {
                try {
                    fs.close();
                    inStream.close();
                } catch (IOException e) {
                    logger.error("closed stream error!", e);
                }

            }

        }
    }

    /**
     * 验证是记事本格式
     */
    public static boolean isNotepadFormat(String suffix) {
        if (StringUtils.isEmpty(suffix)) {
            return false;
        }
        suffix = suffix.trim().toLowerCase();
        if (suffix.equals("txt")) {
            return true;
        }
        return false;
    }

    /**
     * 写入txt文件中(覆盖)
     */
    public static void contentToTxt(String filePath, String content) {
        String s1 = new String();// 内容更新
        try {
            File f = new File(filePath);
            if (f.exists()) {
                System.out.print("文件存在");
            } else {
                System.out.print("文件不存在");
                f.createNewFile();// 不存在则创建
            }
            BufferedReader input = new BufferedReader(new FileReader(f));

            System.out.println(s1);
            input.close();
            s1 += content;
            Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(filePath), GlobalConstant.UTF8));
            out.write(s1);
            out.close();
        } catch (Exception e) {
            e.printStackTrace();

        }
    }

    /**
     * 写入txt文件中
     */
    public static void createFile(String filePath) {
        try {
            File f = new File(filePath);
            if (!f.exists()) {
                f.createNewFile();
            }
        } catch (Exception e) {
            logger.error(String.format("FileUtil.createFile:%s", e));
        }
    }

    /**
     * 获取文件后缀名,后缀名全小写。
     *
     * @param fileName
     *            文件名，不包含文件的路径
     * @return 后缀名,后缀名全小写。如果没有后缀名,返回null
     */
    public static String getSuffix(String fileName) {
        int index = fileName.lastIndexOf('.');
        if (index == -1) {
            return null;
        }

        return fileName.substring(index + 1).toLowerCase();
    }
}
